package com.work.work.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.work.work.dto.ProjectCreateDTO;
import com.work.work.dto.ProjectDTO;
import com.work.work.dto.ProjectReportDTO;
import com.work.work.dto.ResourceAllocation;
import com.work.work.entity.*;
import com.work.work.mapper.ProgressMapper;
import com.work.work.mapper.ProjectMapper;
import com.work.work.mapper.ProjectResourceMapper;
import com.work.work.mapper.TaskMapper;
import com.work.work.service.ProjectService;
import com.work.work.service.ResourceService;
import com.work.work.service.TeamService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.metadata.Head;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements ProjectService {
    @Autowired
    private TeamService teamService;

    @Autowired
    private ResourceService resourceService;
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private ProgressMapper progressMapper;

    @Autowired
    private ProjectResourceMapper projectResourceMapper;



    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteProject(Integer projectId) {
        // 1. 先释放项目占用的资源
        LambdaQueryWrapper<ProjectResource> resourceWrapper = new LambdaQueryWrapper<>();
        resourceWrapper.eq(ProjectResource::getProjectId, projectId);
        List<ProjectResource> projectResources = projectResourceMapper.selectList(resourceWrapper);

        // 遍历项目资源关系，更新资源数量
        for (ProjectResource pr : projectResources) {
            Resource resource = resourceService.getById(pr.getResourceId());
            if (resource != null && resource.getQuantity() != null) {
                // 释放资源（返还已分配的数量）
                resource.setQuantity(resource.getQuantity().add(pr.getAllocatedQuantity()));
                resourceService.updateById(resource);
            }
        }

        // 2. 删除项目相关的进度记录
        LambdaQueryWrapper<Task> taskWrapper = new LambdaQueryWrapper<>();
        taskWrapper.eq(Task::getProjectId, projectId);
        List<Task> tasks = taskMapper.selectList(taskWrapper);

        for (Task task : tasks) {
            LambdaQueryWrapper<Progress> progressWrapper = new LambdaQueryWrapper<>();
            progressWrapper.eq(Progress::getTaskId, task.getId());
            progressMapper.delete(progressWrapper);
        }

        // 3. 删除项目的所有任务
        taskMapper.delete(taskWrapper);

        // 4. 删除项目资源关联
        projectResourceMapper.delete(resourceWrapper);

        // 5. 删除项目
        return removeById(projectId);
    }
    @Override
    public Double sumTotalBudget() {
        // 获取所有单位为"元"的资源
        LambdaQueryWrapper<Resource> moneyWrapper = new LambdaQueryWrapper<>();
        moneyWrapper.eq(Resource::getUnit, "元");  // 假设字段名为 unit

        List<Resource> moneyResources = resourceService.list(moneyWrapper);
        if (moneyResources.isEmpty()) {
            return 0.0;
        }

        // 计算资金总额
        return moneyResources.stream()
                .map(Resource::getQuantity)
                .filter(qty -> qty != null)
                .map(BigDecimal::doubleValue)
                .reduce(0.0, Double::sum);
    }
    @Override
    public Page<ProjectDTO> searchByProjectName(String projectName, Page<ProjectDTO> page) {
        return baseMapper.selectByProjectName(page, projectName);
    }
    @Override
    public Integer sumTotalManpower() {
        // 获取所有单位为"人"的资源
        LambdaQueryWrapper<Resource> manpowerWrapper = new LambdaQueryWrapper<>();
        manpowerWrapper.eq(Resource::getUnit, "人");  // 假设字段名为 unit

        List<Resource> humanResources = resourceService.list(manpowerWrapper);
        if (humanResources.isEmpty()) {
            return 0;
        }

        // 计算人力总数
        return humanResources.stream()
                .map(Resource::getQuantity)
                .filter(qty -> qty != null)
                .map(BigDecimal::intValue)
                .reduce(0, Integer::sum);
    }

    @Override
    public Page<ProjectDTO> pageWithTeamName(Page<ProjectDTO> page) {
        return baseMapper.selectProjectPageWithTeamName(page);
    }

    @Override
public void generateProjectReport(HttpServletResponse response) throws IOException {
    // 1. 获取所有项目数据
    List<Project> projects = projectMapper.selectList(null);
    List<ProjectReportDTO> projectOverviews = new ArrayList<>();
    List<ProjectReportDTO.TaskReportDTO> allTasks = new ArrayList<>();
    LocalDateTime now = LocalDateTime.now();

    // 2. 处理每个项目的数据
    for (Project project : projects) {
        // 2.1 处理项目概览数据
        ProjectReportDTO overview = new ProjectReportDTO();
        overview.setProjectName(project.getProjectName());

        // 获取项目的所有任务
        List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<Task>()
                .eq(Task::getProjectId, project.getId())
                .orderByAsc(Task::getPriority));

        // 计算任务统计信息
        overview.setTotalTasks(tasks.size());
        overview.setCompletedTasks((int) tasks.stream().filter(task -> task.getStatus() == 3).count());
        overview.setInProgressTasks((int) tasks.stream().filter(task -> task.getStatus() == 2).count());
        overview.setNotStartedTasks((int) tasks.stream().filter(task -> task.getStatus() == 1).count());
        overview.setOverdueTasks((int) tasks.stream()
                .filter(task -> task.getEndTime() != null
                        && task.getEndTime().isBefore(now)
                        && task.getStatus() != 3)
                .count());
        overview.setProgress(project.getProgress() + "%");

        projectOverviews.add(overview);

        // 2.2 处理任务详情数据
        List<ProjectReportDTO.TaskReportDTO> projectTasks = tasks.stream()
                .map(task -> {
                    ProjectReportDTO.TaskReportDTO dto = new ProjectReportDTO.TaskReportDTO();
                    dto.setProjectName(project.getProjectName());
                    dto.setTaskName(task.getTaskName());
                    dto.setPriority(task.getPriority());
                    dto.setAssignee(task.getAssignee());
                    dto.setStartTime(task.getStartTime() != null ?
                            task.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) : "");
                    dto.setEndTime(task.getEndTime() != null ?
                            task.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) : "");
                    dto.setStatus(convertStatus(task.getStatus()));
                    return dto;
                })
                .collect(Collectors.toList());

        allTasks.addAll(projectTasks);
    }

    // 3. 配置响应头
    response.setContentType("application/vnd.ms-excel");
    response.setCharacterEncoding("utf-8");
    String fileName = URLEncoder.encode("项目任务报表", "UTF-8");
    response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

    // 4. 使用ExcelWriter写入多个sheet
    try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build()) {
        // 4.1 写入项目概览sheet，设置默认列宽为20
        WriteCellStyle headStyle = new WriteCellStyle();
        WriteCellStyle contentStyle = new WriteCellStyle();

        WriteSheet overviewSheet = EasyExcel.writerSheet(0, "项目概览")
                .head(ProjectReportDTO.class)
                .registerWriteHandler(new com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy(20))
                .build();
        excelWriter.write(projectOverviews, overviewSheet);

        // 4.2 写入任务详情sheet，设置默认列宽为20
        WriteSheet taskSheet = EasyExcel.writerSheet(1, "任务详情")
                .head(ProjectReportDTO.TaskReportDTO.class)
                .registerWriteHandler(new com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy(20))
                .build();
        excelWriter.write(allTasks, taskSheet);
    }
}

    private String convertStatus(Integer status) {
        return switch (status) {
            case 1 -> "未开始";
            case 2 -> "进行中";
            case 3 -> "已完成";
            default -> "未知";
        };
    }
//    @Override
//    @Transactional
//    public boolean createProject(Project project) {
//        // 设置默认状态为未开始
//        if (project.getStatus() == null) {
//            project.setStatus(1);
//        }
//        return save(project);
//    }

    @Override
    public boolean createProject(ProjectCreateDTO projectDTO) {
        // 1. 验证团队是否存在
        Team team = teamService.getById(projectDTO.getTeamId());
        if (team == null) {
            throw new RuntimeException("指定的团队不存在");
        }

        // 2. 验证资源分配
        if (projectDTO.getResourceAllocations() == null || projectDTO.getResourceAllocations().isEmpty()) {
            throw new RuntimeException("至少需要分配一个资源");
        }

        // 3. 验证所有资源是否存在并检查数量是否足够
        for (ResourceAllocation allocation : projectDTO.getResourceAllocations()) {
            Resource resource = resourceService.getById(allocation.getResourceId());
            if (resource == null) {
                throw new RuntimeException("资源ID " + allocation.getResourceId() + " 不存在");
            }
            if (resource.getQuantity().compareTo(allocation.getAllocatedQuantity()) < 0) {
                throw new RuntimeException("资源 " + resource.getResourceName() + " 数量不足");
            }
        }

        // 4. 创建项目
        Project project = new Project();
        project.setProjectName(projectDTO.getProjectName());
        project.setStartTime(projectDTO.getStartTime());
        project.setEndTime(projectDTO.getEndTime());
        project.setDescription(projectDTO.getDescription());
        project.setStatus(projectDTO.getStatus());
        project.setTeamId(projectDTO.getTeamId());

        // 5. 保存项目
        boolean saved = save(project);
        if (!saved) {
            throw new RuntimeException("项目创建失败");
        }

        // 6. 分配资源并更新资源数量
        for (ResourceAllocation allocation : projectDTO.getResourceAllocations()) {
            // 插入项目资源关联记录
            baseMapper.insertProjectResource(
                    project.getId(),
                    allocation.getResourceId(),
                    allocation.getAllocatedQuantity()
            );

            // 更新资源剩余数量
            resourceService.deductResourceQuantity(
                    allocation.getResourceId(),
                    allocation.getAllocatedQuantity()
            );
        }

        return true;
    }
    @Override
    public void updateProjectProgress(Integer projectId) {
        // 获取项目的所有任务
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Task::getProjectId, projectId);
        List<Task> tasks = taskMapper.selectList(queryWrapper);

        if (tasks.isEmpty()) {
            return;
        }

        // 计算已完成的任务数量
        long completedTasks = tasks.stream()
                .filter(task -> task.getStatus() == 3)  // 状态为3表示已完成
                .count();

        // 计算进度百分比
        BigDecimal progress = new BigDecimal(completedTasks)
                .divide(new BigDecimal(tasks.size()), 2, BigDecimal.ROUND_HALF_UP)
                .multiply(new BigDecimal(100));

        // 更新项目进度
        Project project = new Project();
        project.setId(projectId);
        project.setProgress(progress);
        updateById(project);
    }

    @Override
    public long countTotalProjects() {
        // 使用 projectMapper 查询项目总记录数
        return projectMapper.selectCount(null);
    }
}